home *** CD-ROM | disk | FTP | other *** search
- /*------------------------------------------------------------------------------
- #
- # GDeviceUtils.cp
- #
- # by Eric Traut
- #
- ------------------------------------------------------------------------------*/
-
- #include "GDeviceUtils.h"
-
- #include <Memory.h>
- #include <LowMem.h>
- #include <Displays.h>
- #include <Traps.h>
- #include <Resources.h>
- #include <Sound.h>
-
-
- /*---------------------------------------------------------------
- GraphicSurface
- ---------------------------------------------------------------*/
-
- GraphicSurface::GraphicSurface()
- {
- // Nothing to do
- mPixelData = NULL;
- }
-
-
- /*---------------------------------------------------------------
- ExtractRealDeviceInfo
- ---------------------------------------------------------------*/
-
- void
- GraphicSurface::ExtractRealDeviceInfo(
- GDHandle inGDevice)
- {
- PixMapHandle pixMap;
-
- pixMap = inGDevice[0]->gdPMap;
-
- mRowBytes = pixMap[0]->rowBytes & 0x3FFF;
- mPixelData = (UInt8 *)pixMap[0]->baseAddr;
- mBitDepth = pixMap[0]->pixelSize;
- mHeight = pixMap[0]->bounds.bottom - pixMap[0]->bounds.top;
- mWidth = pixMap[0]->bounds.right - pixMap[0]->bounds.left;
- }
-
-
- /*---------------------------------------------------------------
- CapturedGDevice
- ---------------------------------------------------------------*/
-
- CapturedGDevice::CapturedGDevice()
- {
- mGDHandle = NULL;
- mDeviceCaptured = false;
-
- mVirtualDevice = NULL;
-
- mBlendEffect = NULL;
- }
-
-
- /*---------------------------------------------------------------
- ~CapturedGDevice
- ---------------------------------------------------------------*/
-
- CapturedGDevice::~CapturedGDevice()
- {
- if (mDeviceCaptured)
- UncaptureDevice();
- }
-
-
- /*---------------------------------------------------------------
- CaptureDevice
- ---------------------------------------------------------------*/
-
- void
- CapturedGDevice::CaptureDevice(
- GDHandle inGDevice,
- VirtualGDevice * inVDevice)
- {
- if (mDeviceCaptured)
- UncaptureDevice();
-
- mGDHandle = inGDevice;
-
- OSErr err = ::DMGetDisplayIDByGDevice(inGDevice, &mDisplayID, false);
- if (err != noErr)
- DebugStr("\pCouldn't get DisplayID");
-
- mCapturedSurface.ExtractRealDeviceInfo(mGDHandle);
-
- // For now, we only support 16-bit mode.
- if (mCapturedSurface.GetBitDepth() != 16)
- {
- // fix me - report an error
- SysBeep(0);
- }
- else
- {
- mVirtualDevice = inVDevice;
-
- ::HideCursor();
-
- Handle tempHandle = NULL;
-
- // Tell the virtual monitor to initialize itself.
- inVDevice->Initialize(*this, tempHandle);
-
- ::DMSetMainDisplay(inVDevice->GetGDHandle(), tempHandle);
-
- // We need to recompute the GDHandle from the display ID
- // because they may have been rearranged.
- RecomputeGDHandle();
- inVDevice->RecomputeGDHandle();
-
- // Now get rid of the rounded area in the corners
- SetDeviceAttribute(inVDevice->GetGDHandle(), roundedDevice, false);
-
- // Force a complete redraw now.
- UInt32 depth = 16;
- ::DMSetDisplayMode(inVDevice->GetGDHandle(), 100, &depth, 0, NULL);
-
- ::ShowCursor();
-
- mDeviceCaptured = true;
- }
- }
-
-
- /*---------------------------------------------------------------
- UncaptureDevice
- ---------------------------------------------------------------*/
-
- void
- CapturedGDevice::UncaptureDevice()
- {
- if (mDeviceCaptured)
- {
- RecomputeGDHandle();
- OSErr err = ::DMSetMainDisplay(mGDHandle, NULL);
- if (err != noErr)
- DebugStr("\p Error SetMainDisplay");
- RecomputeGDHandle();
-
- // Tell each of the virtual monitors to
- // uninitialize itself.
- if (mVirtualDevice != NULL)
- mVirtualDevice->Uninitialize();
-
- mDeviceCaptured = false;
- }
- }
-
-
- /*---------------------------------------------------------------
- SetPixelBase
- ---------------------------------------------------------------*/
-
- void
- CapturedGDevice::SetPixelBase(
- UInt8 * inPixelBase)
- {
- PixMapHandle pixMap;
-
- RecomputeGDHandle();
- if (mGDHandle != NULL)
- {
- pixMap = mGDHandle[0]->gdPMap;
- pixMap[0]->baseAddr = (Ptr)inPixelBase;
- }
- }
-
-
- /*---------------------------------------------------------------
- UpdateCapturedScreen
- ---------------------------------------------------------------*/
-
- void
- CapturedGDevice::UpdateCapturedScreen()
- {
- if (mBlendEffect != NULL)
- mBlendEffect->RenderVirtualDevice(mCapturedSurface, mVirtualDevice);
- }
-
-
- /*---------------------------------------------------------------
- RecomputeGDHandle
- ---------------------------------------------------------------*/
-
- void
- CapturedGDevice::RecomputeGDHandle()
- {
- OSErr err;
-
- err = ::DMGetGDeviceByDisplayID(mDisplayID, &mGDHandle, false);
-
- if (err != noErr)
- {
- DebugStr("\pFailedToFindDevice");
- mGDHandle = NULL;
- }
- }
-
-
- /*---------------------------------------------------------------
- SetGraphicBlendEffect
- ---------------------------------------------------------------*/
-
- void
- CapturedGDevice::SetGraphicBlendEffect(
- GraphicBlendEffect * inBlendEffect)
- {
- if (mBlendEffect != NULL)
- {
- GraphicBlendEffect * tempEffect = mBlendEffect;
-
- // Set it to NULL first so time manager
- // task doesn't call the effect after it's
- // deallocated.
- mBlendEffect = NULL;
- delete tempEffect;
- }
-
- // We need to wipe the dest screen to black
- ClearCapturedScreen();
-
- mBlendEffect = inBlendEffect;
- }
-
-
- /*---------------------------------------------------------------
- ClearCapturedScreen
- ---------------------------------------------------------------*/
-
- void
- CapturedGDevice::ClearCapturedScreen()
- {
- // The simple blend effect simply involves
- // copying the pixels from the first virtual
- // device to the destination surface.
- UInt32 totalRows = mCapturedSurface.GetHeight();
- UInt32 totalCols = mCapturedSurface.GetWidth();
- UInt8 * destPtr;
-
- for (UInt32 row = 0; row < totalRows; row++)
- {
- destPtr = mCapturedSurface.GetPixelDataPtr() + mCapturedSurface.GetRowBytes() * row;
-
- for (UInt32 col = 0; col < totalCols; col++)
- {
- *(UInt16 *)destPtr = 0;
- destPtr += 2;
- }
- }
- }
-
-
- /*---------------------------------------------------------------
- VirtualGDevice
- ---------------------------------------------------------------*/
-
- VirtualGDevice::VirtualGDevice()
- {
- mDeviceBacking = NULL;
- mGDHandle = NULL;
- mAddedToDeviceList = false;
- }
-
-
- /*---------------------------------------------------------------
- ~VirtualGDevice
- ---------------------------------------------------------------*/
-
- VirtualGDevice::~VirtualGDevice()
- {
- Uninitialize();
- }
-
-
- /*---------------------------------------------------------------
- Initialize
- ---------------------------------------------------------------*/
-
- Boolean
- VirtualGDevice::Initialize(
- CapturedGDevice & inRealGDevice,
- Handle inDMConfigHandle)
- {
- // Allocate backing memory for the virtual device
- Ptr backingPtr;
- backingPtr = ::NewPtrClear(inRealGDevice.GetGraphicSurface().GetBackingSize() * 4);
-
- if (backingPtr == NULL)
- return false;
-
- mDeviceBacking = backingPtr;
-
- // Allocate a new GDevice if this isn't the primary
- // virtual device.
-
- // fix me - what is the first parameter?
- mGDHandle = ::NewGDevice(0, -1);
- if (mGDHandle == NULL)
- return false;
- ::HLock((Handle)mGDHandle);
-
- Handle itableHandle;
-
- itableHandle = ::NewHandle(0);
- if (itableHandle == NULL)
- return false;
-
- // Make a default inverse table
- ::MakeITable(NULL, (ITabHandle)itableHandle, 4);
-
- mGDHandle[0]->gdRefNum = 0;
- mGDHandle[0]->gdID = 128;
- mGDHandle[0]->gdType = 2;
- mGDHandle[0]->gdITable = (ITabHandle)itableHandle;
- mGDHandle[0]->gdFlags = (1L << gdDevType) | // Color device
- (1L << noDriver) | // No driver
- (1L << screenDevice) | // It's a screen device (not printer)
- (1L << screenActive) | // It's active
- (1L << burstDevice);
- mGDHandle[0]->gdMode = 129;
-
- // Set up the device rectangle
- mGDHandle[0]->gdRect.left = 0;
- mGDHandle[0]->gdRect.top = 0;
- mGDHandle[0]->gdRect.right = inRealGDevice.GetGraphicSurface().GetWidth() * 2;
- mGDHandle[0]->gdRect.bottom = inRealGDevice.GetGraphicSurface().GetHeight() * 2;
-
- // Now, set up the pix map for the gdevice
- PixMapHandle realPixMap = inRealGDevice.GetPixMapHandle();
- PixMapHandle virtPixMap = mGDHandle[0]->gdPMap;
-
- // Copy the pix map info
- virtPixMap[0]->baseAddr = mDeviceBacking;
- virtPixMap[0]->rowBytes = ((realPixMap[0]->rowBytes & 0x3FFF) * 2) | (realPixMap[0]->rowBytes & 0xC000);
- virtPixMap[0]->bounds = realPixMap[0]->bounds;
- virtPixMap[0]->bounds.bottom *= 2;
- virtPixMap[0]->bounds.right *= 2;
- virtPixMap[0]->pmVersion = realPixMap[0]->pmVersion;
- virtPixMap[0]->packType = realPixMap[0]->packType;
- virtPixMap[0]->packSize = realPixMap[0]->packSize;
- virtPixMap[0]->hRes = realPixMap[0]->hRes;
- virtPixMap[0]->vRes = realPixMap[0]->vRes;
- virtPixMap[0]->pixelType = realPixMap[0]->pixelType;
- virtPixMap[0]->pixelSize = realPixMap[0]->pixelSize;
- virtPixMap[0]->cmpCount = realPixMap[0]->cmpCount;
- virtPixMap[0]->cmpSize = realPixMap[0]->cmpSize;
- virtPixMap[0]->planeBytes = realPixMap[0]->planeBytes;
- virtPixMap[0]->pmReserved = realPixMap[0]->pmReserved;
-
- if (virtPixMap[0]->pmTable != NULL)
- {
- virtPixMap[0]->pmTable[0]->ctSeed = 0xF;
- virtPixMap[0]->pmTable[0]->ctFlags = 0x8000;
- }
-
- ::DMAddDisplay( mGDHandle,
- mGDHandle[0]->gdRefNum,
- mGDHandle[0]->gdMode,
- 0,
- 0,
- NULL,
- inDMConfigHandle);
- ::DMEnableDisplay(mGDHandle, inDMConfigHandle);
-
- OSErr err = ::DMGetDisplayIDByGDevice(mGDHandle, &mDisplayID, false);
- if (err != noErr)
- DebugStr("\pCouldn't get DisplayID");
-
- mAddedToDeviceList = true;
-
- mVirtualSurface.ExtractRealDeviceInfo(mGDHandle);
-
- return true;
- }
-
-
- /*---------------------------------------------------------------
- Uninitialize
- ---------------------------------------------------------------*/
-
- void
- VirtualGDevice::Uninitialize()
- {
- if (mDeviceBacking != NULL)
- {
- if (mAddedToDeviceList)
- {
- RecomputeGDHandle();
- ::DMRemoveDisplay(mGDHandle, NULL);
- mAddedToDeviceList = false;
- }
-
- if (mGDHandle != NULL)
- ::DisposeGDevice(mGDHandle);
- mGDHandle = NULL;
-
- ::DisposePtr(mDeviceBacking);
- mDeviceBacking = NULL;
- }
- }
-
-
- /*---------------------------------------------------------------
- RecomputeGDHandle
- ---------------------------------------------------------------*/
-
- void
- VirtualGDevice::RecomputeGDHandle()
- {
- OSErr err;
-
- err = ::DMGetGDeviceByDisplayID(mDisplayID, &mGDHandle, false);
-
- if (err != noErr)
- {
- DebugStr("\pFailedToFindDevice");
- mGDHandle = NULL;
- }
- else
- {
- // Reset the backing address. It seems
- // to get reset when we set the main device.
- mGDHandle[0]->gdPMap[0]->baseAddr = mDeviceBacking;
- }
- }
-
-
- /*---------------------------------------------------------------
- LargeBlendEffect
- ---------------------------------------------------------------*/
-
- LargeBlendEffect::LargeBlendEffect()
- {
- mCircleData = ::Get1Resource('Circ', 128);
-
- if (mCircleData != NULL)
- ::HLockHi(mCircleData);
-
- mMagnify = false;
- }
-
-
- /*---------------------------------------------------------------
- BlendPixels
- ---------------------------------------------------------------*/
-
- inline UInt16
- LargeBlendEffect::BlendPixels(
- UInt16 inPixel1,
- UInt16 inPixel2,
- UInt32 inFraction)
- {
- UInt32 red = ((inPixel1 >> 10) & 0x1f) * inFraction;
- UInt32 green = ((inPixel1 >> 5) & 0x1f) * inFraction;
- UInt32 blue = (inPixel1 & 0x1f) * inFraction;
- UInt32 negFrac = 0x100 - inFraction;
-
- red += ((inPixel2 >> 10) & 0x1f) * negFrac;
- green += ((inPixel2 >> 5) & 0x1f) * negFrac;
- blue += (inPixel2 & 0x1f) * negFrac;
-
- return ((red >> 8) << 10) | ((green >> 8) << 5) | (blue >> 8);
- }
-
-
- /*---------------------------------------------------------------
- AveragePixels
- ---------------------------------------------------------------*/
-
- inline UInt16
- LargeBlendEffect::AveragePixels(
- UInt16 inPixel1,
- UInt16 inPixel2,
- UInt16 inPixel3,
- UInt16 inPixel4)
- {
- UInt16 red = ((inPixel1 >> 10) & 0x1f) + ((inPixel2 >> 10) & 0x1f) + ((inPixel3 >> 10) & 0x1f) + ((inPixel4 >> 10) & 0x1f);
- UInt16 green = ((inPixel1 >> 5) & 0x1f) + ((inPixel2 >> 5) & 0x1f) + ((inPixel3 >> 5) & 0x1f) + ((inPixel4 >> 5) & 0x1f);
- UInt16 blue = (inPixel1 & 0x1f) + (inPixel2 & 0x1f) + (inPixel3 & 0x1f) + (inPixel4 & 0x1f);
-
- return ((red / 4) << 10) | ((green / 4) << 5) | (blue / 4);
- }
-
-
- /*---------------------------------------------------------------
- RenderVirtualDevice
- ---------------------------------------------------------------*/
-
- void
- LargeBlendEffect::RenderVirtualDevice(
- const GraphicSurface & inDestSurface,
- VirtualGDevice * inVDevice)
- {
- // The panel blend effect simply involves
- // copying some pixels from the first virtual
- // device to the destination surface.
- UInt32 totalRows = inDestSurface.GetHeight();
- UInt32 totalCols = inDestSurface.GetWidth();
- UInt8 * srcPtr;
- UInt8 * destPtr;
- UInt32 destRowBytes = inDestSurface.GetRowBytes();
- UInt32 srcRowBytes = inVDevice->GetGraphicSurface().GetRowBytes();
- Rect circleRect;
- UInt8 * circleData = (UInt8 *)*mCircleData;
- Point mouseLoc;
- double dblBuffer;
- UInt16 * dblBuffer2 = (UInt16 *)&dblBuffer;
- UInt32 bufferBytes = 0;
-
- mouseLoc = LMGetMouseLocation();
-
- circleRect.left = (mouseLoc.h - kCircleWidth) / 2;
- circleRect.top = (mouseLoc.v - kCircleWidth) / 2;
- circleRect.right = circleRect.left + kCircleWidth;
- circleRect.bottom = circleRect.top + kCircleWidth;
-
- // Blit the first two screens
- for (SInt32 row = 0; row < totalRows; row++)
- {
- destPtr = inDestSurface.GetPixelDataPtr() + destRowBytes * row;
- srcPtr = inVDevice->GetGraphicSurface().GetPixelDataPtr() + srcRowBytes * row * 2;
-
- for (SInt32 col = 0; col < totalCols; col++)
- {
- UInt16 avePixel;
- avePixel = AveragePixels(
- *(UInt16 *)srcPtr,
- *(UInt16 *)(srcPtr + 2),
- *(UInt16 *)(srcPtr + srcRowBytes),
- *(UInt16 *)(srcPtr + srcRowBytes + 2));
-
- if (mMagnify &&
- row >= circleRect.top &&
- row < circleRect.bottom &&
- col >= circleRect.left &&
- col < circleRect.right)
- {
- UInt32 blendAmount = circleData[(row - circleRect.top) * kCircleWidth + (col - circleRect.left)];
-
- UInt8 * bigSrcPtr = inVDevice->GetGraphicSurface().GetPixelDataPtr();
- bigSrcPtr += (circleRect.top * 2 + row - circleRect.top + kCircleWidth / 2) * srcRowBytes;
- bigSrcPtr += (circleRect.left * 2 + col - circleRect.left + kCircleWidth / 2) * 2;
- UInt16 realPixValue = *(UInt16 *)bigSrcPtr;
-
- dblBuffer2[bufferBytes++] = BlendPixels(avePixel, realPixValue, blendAmount);
- }
- else
- {
- dblBuffer2[bufferBytes++] = avePixel;
- }
-
- if (bufferBytes >= 4)
- {
- *(double *)destPtr = dblBuffer;
- bufferBytes = 0;
- destPtr += 8;
- }
-
- srcPtr += 4;
- }
- }
- }
-
-
-
-
-
-